use std::fmt::Debug;
use std::ops::Neg;
use std::*;

///https://paper.yanxishe.com/TextTranslation/3200
#[derive(Debug)]
struct Vec2<'a> {
    x: i32,
    y: &'a str,
}
#[derive(Debug, PartialEq)]
struct Number {
    odd: bool,
    value: i32,
}
trait Signed {
    fn is_strict_positive(&mut self) -> bool;
    fn is_bigger(&mut self, other: Number);
}
trait Signed2 {
    ///&self 和self的区别，调用方法时，给外部暴露了对象本身。此时&表示暴露了对象本身的引用。
    /// self表示对象本身，对象本身传递给fn了，所有权也会转移，转移到fn里面。
    /// 此时再调用这个方法就不可以了。如果 Struct 继承了copy clone，则可以。
    fn is_strict_positive2(&self) -> bool;
    fn is_bigger2(&self, other: Number) -> bool;
}
impl Signed for Number {
    fn is_strict_positive(&mut self) -> bool {
        self.value = 10;
        self.value > 0
    }

    fn is_bigger(&mut self, other: Number) {
        println!("self:{:?}", self);
        println!("other:{:?}", other);
    }
}
impl Signed2 for Number {
    fn is_strict_positive2(&self) -> bool {
        self.value > 0
    }
    fn is_bigger2(&self, other: Number) -> bool {
        self.value > other.value
    }
}
#[test]
pub fn test_trait_impl() {
    let mut n1 = Number {
        odd: true,
        value: 9,
    };
    let n2 = Number {
        odd: false,
        value: 10,
    };
    println!("{:?}", n1.is_strict_positive());
    println!("{:?}", n1.is_strict_positive()); //
    println!("{:?}", n1.is_bigger(n2));
    println!("{:?}", n1);

    println!("{:?}", n1.is_strict_positive2());
}

#[test]
pub fn test1() {
    let x = vec![1, 2, 3, 4, 5]
        .iter()
        .map(|i| i + 3)
        .fold(0, |x, y| x + y);
    println!("x fold = {:?}", x);
}

#[test]
pub fn test2() {
    greet();
    println!("roll:{:?}", roll());
    let min = cmp::min(3, 6);
    println!("min:{:?}", min);
}
#[test]
pub fn testStructUpdate() {
    let v1 = Vec2 { y: "abc", x: 32 };
    ///There is a shortcut for initializing the rest of the fields from another struct: ..v1 讲v1的其他field灌入新struct。
    /// struct update syntax struct更新语法，不能在v1对象后面加上逗号了。
    let v3 = Vec2 { x: 12, ..v1 };
    ///struct更新 语法 没有实现move和copy
    let v4 = Vec2 { ..v1 }; //包括所有的另一个struct的里面的内容。
    println!("{:?}", v1);
    println!("{:?}", v3);
    println!("{:?}", v4);
    let (left, right) = "abcde".split_at(2);
    println!("l={:?},r={:?}", left, right);

    //用结构体 解构v4对象。 deconstruct拆析
    let Vec2 { x, y } = v4;
    println!("x={:?},y={:?}", x, y);
}
#[test]
fn testPatterIfStructUpdate() {
    let one = Number {
        odd: true,
        value: 1,
    };
    let two = Number {
        odd: false,
        value: 2,
    };
    let three = Number {
        odd: true,
        value: 3,
    };
    let four = Number {
        odd: false,
        value: 4,
    };
    let five = Number {
        odd: true,
        value: 5,
    };
    print_number(one);
    print_number(two);
    // print_number_match_struct( one);
    // print_number_match_struct(two);
    print_number_match_struct(three);
    print_number_match_struct(four);
    // print_number_by_value(four);
    print_number_by_value(five);
}
fn print_number(num: Number) {
    //结构体半赋值，匹配已经存在的值，则进行赋值。otherwise
    if let Number { odd: true, value } = num {
        println!("n={:?}", num);
        println!("value={:?}", value);
    } else if let Number { odd: false, value } = num {
        println!("even number:");
        println!("value={:?}", value);
    }
}
fn print_number_match_struct(n: Number) {
    //match 是表达式，跟java的match不一样。里面各个分支都是逗号。
    //支持半struct匹配。
    match n {
        Number { odd: true, value } => println!("odd number:{:?}", value),
        Number { odd: false, value } => println!("even number:{:?}", value),
        Number { odd, value: 3 } => println!("3, and odd is:{:?}", odd),
        //at least one arm needs to match.
        Number { odd, value: 4 } => println!("4, and odd is:{:?}", odd),
    }
}
fn print_number_by_value(n: Number) {
    match n.value {
        1 => println!("1"),
        2 => println!("2"),
        // _ match all
        _ => println!("other bigger than 2: {:?}", n.value),
    }
}

fn greet() {
    /// unbelievable  return println.
    return println!("welcome");
}
fn roll() -> i32 {
    38
}
#[test]
fn test_mutable() {
    //整个struct可变，则里面的field也可以变
    let mut n = Number {
        odd: true,
        value: 3,
    };
    n.value = 10;
    println!("{:#?}", n);
    dbg!(&n);
    dbg!(&n);
}

impl std::ops::Neg for Number {
    type Output = Self;
    fn neg(self) -> Self {
        Number {
            value: -self.value,
            odd: self.odd,
        }
    }
}
#[test]
fn testNeg() {
    let n1 = Number {
        value: 789,
        odd: true,
    };
    let n2 = -n1;
    println!("{:?}", n2)
}
#[test]
fn testMove() {
    //i32 impl copy
    let a: i32 = 4;
    print_t(a); //a is copied
    print_t(a); //a is copied
    let b = a; //copied
    print_t(b); //b is copied
    let n1 = Number {
        odd: true,
        value: 13,
    };
    let n2 = n1; // n1 is moved to n2 .
                 // print_t(n1); // n1 is lost.
    let n3 = &n2; //`n2` is borrowed
                  // let n4=&mut n2;//Cannot borrow immutable local variable `n2` as mutable
                  //n2 is immutable can not cast to mutable afterwards.
    print_t(n3); // print_t accept:obj &obj &mut obj都可以，都是这个内存对象。只是对这个对象的使用的RW做了限制。
                 //we say that rust can acl to memo not only by length limit but also by RW control.
                 // print_t(n4);
}
fn print_t<T: Debug>(i: T) {
    println!("a={:?}", i);
}
fn invert(n: &mut Number) {
    n.value = -n.value;
}
#[test]
fn test_invert() {
    let mut n1 = Number {
        odd: true,
        value: 23,
    }; //可变对象
    print_t(&n1); //use immutable ref
    invert(&mut n1); //use mutable ref  `n is borrowed mutably - everything is explicit
    print_t(&n1); //use immutable ref

    let n2 = &n1;
    let mut n3 = n2.clone(); // n3 now still is type :Number but has a W acl.
    print_t(&n3); // use n3 R acl.
    n3.value += 100; //use n3 W acl.
    print_t(&n3);
    print_t(&n2);
    // print_t(n3);
    // print_t(n3);
    print(&n3);
    compare(n2, &n1);
    compare(n2, &n3);
}

impl std::clone::Clone for Number {
    //represent &self &mut self。 R/W acl to self obj。
    fn clone(&self) -> Self {
        Number { ..*self } //*self    *& 代表解引用
    }
}
// impl std::marker::Copy for Number{}
fn print<T>(value: T)
where
    T: Debug,
{
    println!("value={:?}", value);
}
fn compare<T>(left: T, right: T)
where
    T: Debug + PartialEq,
{
    println!(
        "{:?} {} {:?}",
        left,
        if (left == right) { "==" } else { "!=" },
        right
    );
}
#[test]
//turbo fish syntax   ::<T>  specify the Type in generic syntax.
fn test_generic() {
    use std::any::type_name;
    println!("{}", type_name::<i32>()); //i32
    println!("{}", type_name::<Number>()); //ownership::study_in_half_hour::Number
    println!("{}", type_name::<(i32, Number)>()); //(i32, ownership::study_in_half_hour::Number)
}
struct Pair<T> {
    a: T,
    b: T,
}
fn print_type_name<T>(val: &T) {
    println!("{}", std::any::type_name::<T>())
}
#[test]
fn test_pair() {
    let a = Pair { a: 9, b: 10 };
    let b = Pair {
        a: "abc".to_string(),
        b: "ccc".to_string(),
    };
    print_type_name(&a);
    print_type_name(&b);
    let mut v1 = Vec::new();
    v1.push(1);
    let mut v2 = Vec::new();
    v2.push("abc");
    print_type_name(&v1);
    print_type_name(&v2);
}
#[test]
fn test_panic() {
    panic!("throw panic ..");
}
#[test]
fn test_panic2() {
    let o1 = Some(1);
    o1.unwrap();
    let o2: Option<i32> = None;
    o2.unwrap();
    //thread 'study_in_half_hour::test_panic2' panicked at 'called `Option::unwrap()` on a `None` value'
}
#[test]
fn test_move2() {
    {
        let x = Number {
            odd: true,
            value: 5,
        };
        let x_ref = &x;
        print(x_ref);
        print(x_ref); //& immutable ref not move.
                      // A variable binding can be immutably borrowed multiple times
        print(&x);
        print(x); //obj moved to fn.  `x` stops existing
                  // print(x_ref); //----- borrow later used here
    }
}
#[test]
fn test_borrow() {
    let mut a = 42;
    let b = &a;
    //a=23; // assignment to borrowed `a` occurs here
    //mut a被borrow后就不允许再对其赋值了。
    print(b);
}
#[test]
fn test_borrow2() {
    let mut a = 42;
    let b = &a;
    //let b2=&mut a;  //mutable borrow occurs here
    //a already borrowed . and other can not borrow as mutable
    print(b);
}
#[test]
fn test_borrow3() {
    print3(&32);
}
fn print3(x: &i32) {
    // `x` is borrowed (from the outside) for the
    // entire time this function is called.
    /// Functions with reference arguments can be called with borrows that have different lifetimes
    ///lifetime 'a generic type.
    /// All functions that take references are generic 所有有参数的方法都是范型
    /// Lifetimes are generic parameters 生命周期是范型
    println!("{}", x);
}
#[test]
fn test_generic3() {
    let n = Number {
        value: 23,
        odd: true,
    };
    println!("{}", number_value(&n));
    println!("{}", number_value2(&n));
}

fn number_value<'a>(n: &'a Number) -> &'a i32 {
    &n.value
}
///When there is a single input lifetime, it doesn't need to be named('a)
fn number_value2(n: &Number) -> &i32 {
    &n.value
}

struct NumRef<'a> {
    //let this struct hold a i32 ref
    x: &'a i32,
}
#[test]
fn test_num_ref() {
    let a = 32;
    let nRef = NumRef { x: &a };
    println!("{}", nRef.x);
    println!("{}", as_num_ref(&a).x);
    println!("{}", nRef.as_num_ref());
}
fn as_num_ref(n: &i32) -> NumRef {
    NumRef { x: n }
}

//indicate the anonymous lifetime: `<'_>`
///Struct generic usage.
//<'_> can't refer life time so   means 'static,
// which is valid for the entire program's lifetime!!
// alias 'static
impl<'a> NumRef<'a> {
    fn as_num_ref(&'a self) -> &'a i32 {
        self.x
    }
}

struct Person {
    name: &'static str,
}
#[test]
fn test_person_lifetime() {
    let p = Person { name: "xiaow" };
    let name = format!("faster than {}", "lime");
    ///let p2=Person{name:&name}; // borrowed value does not live long enough
    ///Person name is static lone time but name1 can not assure that.
    // this usage requires that `name1` is borrowed for `'static`
    // println!("{}",p2.name);
    println!("{}", p.name);
}
#[test]
fn test_slice_vec() {
    let v = vec![1, 2, 3, 4, 5];
    let v2 = &v[2..4];
    for i in 0..v2.len() {
        println!("{}", v2[i]);
    }

    println!("{:?}", v2);
    // println!("{}",v2); //v2 need impl Display .
}
#[test]
fn test_range() {
    println!("(0..).contains(&100) : {:?}", (0..).contains(&100)); //比0大的数集合
    println!("(0..20).contains(&20): {:?}", (0..20).contains(&20)); //[0-20)集合但是不包括20
    println!("(0..=20).contains(&20):{:?}", (0..=20).contains(&20)); //[0-20] 包括20
    println!("(3..6).contains(&4): {:?}", (3..6).contains(&4));
    let v1: Vec<u8> = vec![1, 2, 3, 4];
    let v2 = tail(&v1);
    println!("{:?}", v2);
}
fn tail(range: &[u8]) -> &[u8] {
    &range[1..]
}

fn file_ext(name: &str) -> Option<&str> {
    name.split(".").last()
}
#[test]
fn test_str_slice() {
    let file = "Read me. Or don't.txt";
    println!("{:?}", file_ext(&file).unwrap_or(""));
    // let ext = {
    //     let name = String::from("Read me. Or don't.txt");
    //     file_ext(&name).unwrap_or("")
    // borrowed value does not live long enough
    // };
    // println!("{:?}", ext)
}
#[test]
fn test_result_err_handle() {
    let s = std::str::from_utf8(&[240, 159, 141, 137]);
    println!("{:?}", s); //no error
    let s1 = std::str::from_utf8(&[195, 40]);
    println!("{:?}", s1); //err but no panic
                          //unwrap leads to panic
    ///valid utf-8: Utf8Error 自定义Err Msg
    // let s2 = std::str::from_utf8(&[195, 40]).expect("valid utf-8 222");
    match std::str::from_utf8(&[195, 40]) {
        Ok(rst) => println!("{:?}", rst),
        Err(err) => println!("{:?}", err.to_string()),
    }
    if let Ok(rst) = std::str::from_utf8(&[240, 159, 141, 137]) {
        println!("rst={:?}", rst);
    }
}

fn multi<F>(f: F) -> i32
where
    F: Fn(i32) -> i32,
{
    f(f(2))
}
fn each_plant<F>(f: F)
where
    F: Fn(&'static str),
{
    f("Mars");
    f("Jupiter");
    f("Earth");
}
fn each_plant2<F>(f: F)
where
    F: Fn(&'static str) + 'static,
{
    f("Mars");
    f("Jupiter");
    f("Earth");
}
#[test]
fn test_closure() {
    //2*2 * 2*2
    println!("{}", multi(|x| x * x));
    // Welcome "Mars"
    // Welcome "Jupiter"
    // Welcome "Earth"
    each_plant(|x| println!("Welcome {:?}", x));
    let greeting = String::from("Good to see you");
    // Good to see you "Mars"
    // Good to see you "Jupiter"
    // Good to see you "Earth"
    // our closure borrows `greeting`, so it cannot outlive it}
    each_plant(|x| println!("{} {:?}", &greeting, x));
    /// each_plant2 may outlive borrowed value `greeting`  as each_plant2 入参数和本身都是static的。所以greeting可能提早就lost了。
    // each_plant2(|x|println!("{} {:?}",&greeting,x));

    ///这种可以，greeting不再borrow，而是直接move了。
    each_plant2(move |x| println!("{} {:?}", greeting, x));
    // variable moved due to use in closure，所以之后也不能使用greeting了 已经lost到fn里面了。
    // each_plant(|x|println!("{} {:?}",&greeting,x));
}

fn fnmut_test<F>(mut mu: F, i: i32)
where
    F: FnMut(i32) -> i32,
{
    // mu(mu(i))  //second mutable borrow occurs here
    let mut inner = 2;
    inner += i;
    let mid = mu(inner);
    let rst = mu(mid);
    println!("rst={:?}", rst);
}

fn fnmut_test2<F>(mut mu: F) //给FnMut方法对象一个W权限。
where
    F: FnMut(i32) -> i32,
{
    // mu(mu(i))  //second mutable borrow occurs here
    let mid = mu(2);
    let rst = mu(mid);
    println!("rst={:?}", rst);
}
#[test]
fn test_fn_mut() {
    fnmut_test(|x| x * 2, 3);
    let mut local_variable = 3;
    //FnMut借用外部的变量，并且操作了外部变量。
    fnmut_test2(|x| {
        local_variable += 1;
        local_variable * x
    });
}
fn fn_once<F>(f:F) where F:FnOnce()->String{
    println!("{:?}",f());
}
#[test]
///They exist because some closure move out variables that have been moved when captured
fn test_fn_once(){
    let s=String::from("test fnOnce");
    fn_once(move||s); //  value moved into closure here
    // fn_once(move||s); // value used here after move
}

fn greater_smaller<F>(l:i32,r:i32,is_greater:F) where F:Fn(i32,i32)->bool,{
    let (greater,smaller) = if is_greater(l,r) { (l,r)} else { (r,l) };
    println!("{:?} is greater than {:?}",greater,smaller);
}
#[test]
fn test_two_paras_closure(){
    greater_smaller(21,22,|x,y|x>y);
    //ignore two parameters.
    greater_smaller(21,22,|_,_|panic!("Comparing is futile!"));
}

fn count_down<F>(limit:u32,tick:F)
where F:Fn(u32),{
    for i in (0..limit).rev() { //range reverse. count down.
        tick(i);
    }
}
#[test]
fn test_tick_down(){
    count_down(20,|x|println!("tick {:?}",x));
    count_down(20,|_|()); //toilet closure that looks like a toilet
}
#[test]
fn test_for_in(){
    //vec iterator
    for i in vec![12,11,13] {
        println!("{:?}",i);
    }
    //char iter
    for i in "abcde".chars() {
        println!("{:?}",i);
    }
    //slice
    for i in &[1,2,3,4,5] {
        println!("{:?}",i);
    }

    for i in "sHE'S brOKen".chars().filter(
        |x|x.is_uppercase() || !x.is_alphabetic())
        .flat_map(|x|x.to_lowercase())
    {
        print!("{}",i); //not {:?} this will add 'a' for every char.
    }
    println!("");
}

fn make_tester(answer:String)-> impl Fn(&str)->bool {
  move  |challenge|answer==challenge   //how to return a closure .
    //borrowed value does not live long enough。 如果所有权不转移则报错，参数可能中途losts。
}
#[test]
fn test_return_closure(){
    let newClosure=make_tester("hill".to_owned());
    println!("guess :{:?}",if newClosure("abc") { "right" } else {"wrong"});
    println!("guess :{:?}",if newClosure("hill") { "right" } else {"wrong"});
}